package org.red5.demo;

import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_objdetect;
import org.bytedeco.javacv.*;
import org.red5.entity.Image;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import static org.red5.demo.ParameterAPI.sWebsocketAPI;

public class Rtsp {
        /**
         * 转流器  最新版
         *
         * @param inputFile
         * @param outputFile
         * @throws Exception
         * @throws org.bytedeco.javacv.FrameRecorder.Exception
         * @throws InterruptedException
         */
        public static void recordPush4(String inputFile, String outputFile, int v_rs) throws Exception, org.bytedeco.javacv.FrameRecorder.Exception, InterruptedException {
            Loader.load(opencv_objdetect.class);
            long startTime = 0;
            Java2DFrameConverter java2DFrameConverter = new Java2DFrameConverter();
            //帧抓取器（FrameGrabber）
            FrameGrabber grabber = FFmpegFrameGrabber.createDefault(inputFile);
            //grabber.setOption("rtsp_transport" , "tcp"); // 使用tcp的方式，不然会丢包很严重
            grabber.setImageWidth(300);
            grabber.setImageHeight(200);
            System.out.println("grabber start");
            try {
                grabber.start();
            } catch (Exception e) {
                try {
                    grabber.restart();
                } catch (Exception e1) {
                    throw e;
                }
            }

            OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
            Frame grabframe = grabber.grab();
            opencv_core.IplImage grabbedImage = null;
            if (grabframe != null) {
                System.out.println("取到第一帧");
                grabbedImage = converter.convert(grabframe);
            } else {
                System.out.println("没有取到第一帧");
            }

            //帧录制器/推流器（FrameRecorder）
            //如果想要保存图片,可以使用 opencv_imgcodecs.cvSaveImage("hello.jpg", grabbedImage);来保存图片
            FrameRecorder recorder;
            try {
                recorder = FrameRecorder.createDefault(outputFile, 1280, 720);
            } catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
                throw e;
            }
            recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264
            recorder.setFormat("flv");
            recorder.setFrameRate(v_rs);
            recorder.setGopSize(v_rs);
            System.out.println("准备开始推流...");
            try {
                recorder.start();
            } catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
                try {
                    System.out.println("录制器启动失败，正在重新启动...");
                    if (recorder != null) {
                        System.out.println("尝试关闭录制器");
                        recorder.stop();
                        System.out.println("尝试重新开启录制器");
                        recorder.start();
                    }

                } catch (org.bytedeco.javacv.FrameRecorder.Exception e1) {
                    throw e;
                }
            }
            System.out.println("开始推流");

            //CanvasFrame frame = new CanvasFrame("camera", CanvasFrame.getDefaultGamma() / grabber.getGamma());


            // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            //frame.setAlwaysOnTop(true);
            while ( //frame.isVisible()  &&
                    (grabframe = grabber.grab()) != null) {
                //System.out.println("推流..."+inputFile);
                //frame.showImage(grabframe);
                grabbedImage = converter.convert(grabframe);
                Frame rotatedFrame = converter.convert(grabbedImage);

                if (startTime == 0) {
                    startTime = System.currentTimeMillis();
                }
                recorder.setTimestamp(1000 * (System.currentTimeMillis() - startTime));//时间戳
                if (rotatedFrame != null) {
                    BufferedImage bufferedImage = java2DFrameConverter.getBufferedImage(rotatedFrame);
                    byte[] bytes = imageToBytes(bufferedImage, "jpg");
                    sWebsocketAPI.sendAllByObject(1, new Image(bytes));
                    recorder.record(rotatedFrame);
                }

                Thread.sleep(40);
            }
            //frame.dispose();
            recorder.stop();
            recorder.release();
            grabber.stop();
            System.exit(2);
        }

    /**
     * 图片转字节数组
     *
     * @param bImage 图片数据
     * @param format 格式
     * @return 图片字节码
     */
    private static byte[] imageToBytes(BufferedImage bImage, String format) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bImage, format, out);
        } catch (IOException e) {
            System.out.println("bufferImage 转 byte 数组异常");
            System.out.println("bufferImage transfer byte[] exception: " + e);
            return null;
        }
        return out.toByteArray();
    }

    public static void runFempeg() {
        String all = "cmd /c start /b ffmpeg -i \"rtsp://admin:12345@192.168.20.13:554/h264/ch1/main/av_stream\" "
                + "-f flv -r 25 -an -s 640*480 \"rtmp://localhost:1935/oflaDemo/192.168.20.15\"";
        String line = null;
        StringBuilder sb = new StringBuilder();
        Runtime runtime = Runtime.getRuntime();
        try {
            System.out.println(all);
            java.lang.Process process = runtime.exec(all);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            while ((line = bufferedReader.readLine()) != null) {
                sb.append(line + "\n");
                System.out.println(line);
                process.destroy();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }



}
